using System;
using System.Collections.Generic;
using System.IO;

namespace Gloom
{
	// Uses gl.tm to map named GL types to GL primitives.
	public static class GLTypePrimitiveMapper
	{
		private static Dictionary<string, string> mapper = new Dictionary<string, string>();
		
		public static bool TryMap(string inType, out string outType, StreamWriter infoLog, StreamWriter errorLog)
		{
			if (mapper.ContainsKey(inType))
			{
				outType = mapper[inType];
				infoLog.WriteLine("GLTypePrimitiveMapper converting " + inType + " to " + outType);
				return true;
			}
			else
			{
				outType = "FAIL";
				errorLog.WriteLine("GLTypePrimitiveMapper no match for `" + inType + "'!");
				infoLog.WriteLine("GLTypePrimitiveMapper no match for `" + inType + "'!");
				return false;
			}
		}
		
		public static string MakeArgNameSafe(string argName)
		{
			// Some argument names for functions overlap with C# keywords and intrinsic types :(
			if (argName == "params")
				argName = "parameters";
			if (argName == "ref")
				argName = "reference";
			if (argName == "base")
				argName = "base_";
			if (argName == "string")
				argName = "str";
			if (argName == "object")
				argName = "obj";
			if (argName == "in")
				argName = "input";
			if (argName == "value")
				argName = "val";
			
			return argName;
		}
		
		public static void Load()
		{
			StreamReader sr = File.OpenText(MainClass.SpecsPath + "gl.tm");
			
			// syntax:
			// comment lines begin with #
			// blank lines too should be ignored
			// useful lines are in the form:  From,*,*,  [some whitespace]  GLTo,*,*
			
			int duplicates = 0;
			
			while (!sr.EndOfStream)
			{
				string line = sr.ReadLine();
				
				if (line.Trim().Length < 1)
					continue;
				if (line.StartsWith("#"))
					continue;
				
				// Otherwise...
				string nline = line.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace(",*", "").Replace(" ", "");
				// So, line should now be in form From,GLTo
				string[] bits = nline.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				
				if (bits[1] == "GLvoid*const") // pain!
					bits[1] = "GLvoid*";
				else if (bits.Length != 2 || (nline.Contains("*") && !bits[1].EndsWith("*")))
					throw new Exception("gl.tm line parse failure. Please debug me!");
				
				if (mapper.ContainsKey(bits[0]))
				{
					if (mapper[bits[0]] != bits[1])
						throw new Exception("gl.tm parsing: Found duplicate key with different value!");
					else
						duplicates++;
				}
				else
					mapper.Add(bits[0], bits[1]);
				
				//Console.WriteLine("DEBUG: i r map " + bits[0] + " to " + bits[1] + ".");
			}
			
			if (duplicates > 0)
				Console.WriteLine("gl.tm parsing: There were " + duplicates.ToString() + " duplicate entries, but the keys and values matched\n" +
					"so it was ok.");
			
			if (mapper.ContainsKey("void"))
				mapper.Remove("void");
			mapper.Add("void", "GLvoid"); // bloody stupid definition in gl.tm, mapping Void to void but void to *. (???)
			
			sr.Close();
		}
	}
}

